#ifndef TABELMK_H
#define TABELMK_H

#include "..\MesinKata\mesinkata.h"
#include "..\LinkedListGeneralDefinition\LinkedListGeneralDefinition.h"
#include "..\Owner\Owner.h"
#include "..\Reader\Reader.h"

struct RECORD_MK {
	string kodeMK; // <-- Key
	string nameMK;
	int SKS;
	string bidang;
	
	struct RECORD_MK *next;
	ownerList _ownerList; // Di node mana saja Record ini di simpan?
};

typedef struct RECORD_MK RecordMK;

#define AddressMK RecordMK*

typedef AddressMK TabelMK;

// DEFINISI NAMA TABEL
#define NAMATABELMK		CharToString("MataKuliah")

// SELEKTOR

#define KODEMK(R)		(R)->kodeMK
#define NAMA_MK(R)		(R)->nameMK
#define SKS(R)			(R)->SKS
#define BIDANG(R)		(R)->bidang

#define TABELMK_NUM_KOLOM	4

// DEFINISI NAMA KOLOM (DALAM BENTUK STRING)
#define Kol_KodeMK		CharToString("KodeMK")
#define Kol_NamaMK		CharToString("NamaMK")
#define Kol_SKS			CharToString("SKS")
#define Kol_Bidang		CharToString("Bidang")

// KONSTRUKTOR - DESTRUKTOR
TabelMK		CreateEmptyTabelMK();
AddressMK	AllocateRecordMK(string KodeMK, string NamaMK, int SKS, string Bidang);
AddressMK	AllocateRecordMKAdv(string KodeMK, string NamaMK, int SKS, string Bidang, AddressMK next);
void 		DeallocateRecordMK(RecordMK *MK);

// PREDIKAT
bool		IsRecordMKEqual(AddressMK A, AddressMK B);

// OPERASI
void		ChangeRecordMKContent(AddressMK MK, string kodebaru, string Namabaru, int SKSBaru, string bidangBaru);

int 		GetRecordMKSize(AddressMK MK);
/**********************************************************************************
	Menghitung size dari RecordMK
	I.S. : 	MK sudah dialokasi
	F.S. : 	return size dari RecordMK
**********************************************************************************/ 

void	 	AddRecordMK(AddressMK MK, TabelMK *TMK);
/**********************************************************************************
	Menambahkan MK ke TMK di tempat yang tepat
	I.S. : 	MK sudah dialokasi
	F.S. : 	TMK berisi MK dan terurut membesar berdasarkan Nama
**********************************************************************************/ 

void	 	DestroyRecordMK(AddressMK MK, TabelMK *TMK);
/**********************************************************************************
	Mendealokasi MK dari TMK.
	I.S. : 	MK ada di dalam TMK
	F.S. : 	MK tidak ada di dalam TMK. MK didealokasi.
**********************************************************************************/ 

AddressMK	SearchRecordMKByKode(string KodeMK, TabelMK *TMK);
/**********************************************************************************
	Mencari alamat Record yang memiliki KodeMK sama dengan KodeMK
	I.S. : 	Sembarang
	F.S. : 	Return address tempat record yang mengandung KodeMK tsb.
			Return NULL jika KodeMK tersebut tidak ditemukan
**********************************************************************************/

AddressMK	SearchRecordMK(AddressMK MK, TabelMK *TMK);
/**********************************************************************************
	Mencari alamat Record MK dalam TMK
	I.S. : 	Sembarang
	F.S. : 	Return address tempat record tersebut ditemukan
			Return NULL jika tidak ditemukan
**********************************************************************************/  

void		AddOwnerToRecordMK(AddressMK MK, ownerAddress O);
/**********************************************************************************
	Menambah owner ke MK
	I.S. :	MK sudah dialokasi, O sudah dialokasi
	F.S. :	O ditambahkan dalam OWNERLIST(MK)
**********************************************************************************/ 

bool 		EvaluateQueryTabelMK(AddressMK MK, Reader R, bool *query_succeed);
/**********************************************************************************
	Mengevaluasi Query dari user
	I.S. : 	MK sudah dialokasi
	F.S. : 	Return hasil query
			query_succeed berisi true apabila query dari user sesuai spesifikasi
			query_succeed berisi true apabila query dari user tidak sesuai spesifikasi
**********************************************************************************/ 

int 		CountRecordMK(TabelMK T);
/**********************************************************************************
	Menghitung jumlah elemen dari T
	I.S. : 	Sembarang, bisa kosong
	F.S. : 	return jumlah elemen dalam T
**********************************************************************************/ 

int			CountNodeRecordMK(TabelMK T, nodeAddress N);
/**********************************************************************************
	Menghitung jumlah elemen di dalam T yang memiliki owner dengan node N
	I.S. : 	Sembarang, bisa kosong
	F.S. : 	return jumlah elemen dalam T yang memiliki owner dengan node N
**********************************************************************************/ 

void		DestroyTabelMK(TabelMK *T);
/**********************************************************************************
	Mendealokasikan semua elemen dari list
	I.S. : 	Sembarang, list bisa kosong
	F.S. : 	TabelMK T menjadi kosong
**********************************************************************************/

// OUTPUT - for testing
void		PrintTabelMK(TabelMK T);
/**********************************************************************************
	Hanya untuk ngetest
**********************************************************************************/ 

void		PrintTabelMKHeader(bool showKode, bool showNama, bool showSKS, bool showBidang);
/**********************************************************************************
	Menampilkan Header TabelMK ke layar.
	Referensi : TabelMhs.h
		
	Lebar kolom :
		Kode		: 10
		Name		: 40
		SKS			: 5
		Bidang		: 25
**********************************************************************************/ 

void		PrintRecordMK(AddressMK MK, bool showKode, bool showNama, bool showSKS, bool showBidang);
/**********************************************************************************
	Menampilkan MK ke layar.
	Referensi : TabelMhs.h
		
	Lebar kolom :
		Kode		: 10
		Name		: 40
		SKS			: 5
		Bidang		: 25
**********************************************************************************/ 

#endif

